package com.tangyh.basic.utils.oldProject;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 身份证图片处理
 *
 * @version V1.0
 * (C)2019-2021 福建省金柠网络科技有限公司. All rights reserved.
 * @author: Alan
 * @createTime: 2021-06-23 11:13
 */
public class PictureUtils {

    /**
     * 截取证件图片并摆正
     *
     * @param data  阿里云返回Json数据
     * @param bytes 图片字节
     * @return boolean
     * @author Alan
     * @date 2021/6/23 14:31
     */
    public static BufferedImage getCardRegionImage(JSONObject data, byte[] bytes) {
        String angle = data.get("angle").toString();
        JSONArray card_region_jsonArray = (JSONArray) data.get("card_region");
        List<Point> cardRegionPointList = cardRegionPointList(card_region_jsonArray);
        //计算截取宽高
        int x = cardRegionPointList.get(0).x;
        int y = cardRegionPointList.get(0).y;
        Integer width = cardRegionPointList.get(1).x - x;
        Integer height = cardRegionPointList.get(3).y - y;
        final BufferedImage cut = cut(bytes, x, y, width, height);
        return straighten(cut, angle);
    }

    /**
     * 截取头像图片并摆正
     *
     * @param data  阿里云返回Json数据
     * @param bytes 图片字节
     * @return boolean
     * @author Alan
     * @date 2021/6/23 14:31
     */
    public static BufferedImage getFaceRectImage(JSONObject data, byte[] bytes) {
        String angle = data.get("angle").toString();
        JSONArray face_rect_vertices_jsonArray = (JSONArray) data.get("face_rect_vertices");
        List<Point> faceRectPointList = faceRectPointList(face_rect_vertices_jsonArray);
        //计算截取宽高
        int x = faceRectPointList.get(0).x;
        int y = faceRectPointList.get(0).y;
        Integer width = faceRectPointList.get(1).x - x;
        Integer height = faceRectPointList.get(3).y - y;
        final BufferedImage cut = cut(bytes, x, y, width, height);
        return straighten(cut, angle);
    }

    /**
     * 图片摆正
     *
     * @param bufferedImage 图片
     * @param angle         旋转角度
     * @return boolean
     * @author Alan
     * @date 2021/6/23 14:26
     */
    public static BufferedImage straighten(BufferedImage bufferedImage, String angle) {
        //角度转换为顺时针旋转角度
        int sourceAngle = Integer.parseInt(angle);
        int actualAngle = 0;
        if (sourceAngle > 0) {
            actualAngle = 360 - sourceAngle;
        } else if (sourceAngle < 0) {
            actualAngle = Math.abs(sourceAngle);
        }
        return Rotate(bufferedImage, actualAngle);
    }

    /**
     * 获取证件位置坐标
     *
     * @param jsonArray 证件位置坐标数组
     * @return java.util.ArrayList<java.awt.Point>
     * @author Alan
     * @date 2021/6/23 14:27
     */
    public static List<Point> cardRegionPointList(JSONArray jsonArray) {
        List<Point> cardRegionPointList = new ArrayList<>();
        for (Object o : jsonArray) {
            Point point = new Point();
            point.x = Integer.parseInt(JSONObject.parseObject(o.toString()).get("x").toString());
            point.y = Integer.parseInt(JSONObject.parseObject(o.toString()).get("y").toString());
            cardRegionPointList.add(point);
        }
        return cardRegionPointList;
    }

    /**
     * 获取头像位置坐标，并排序
     *
     * @param jsonArray 头像坐标数组
     * @return java.util.List<java.awt.Point>
     * @author Alan
     * @date 2021/6/23 14:27
     */
    public static List<Point> faceRectPointList(JSONArray jsonArray) {
        List<Point> faceRectPointList = new ArrayList();
        for (Object o : jsonArray) {
            Point point = new Point();
            point.x = Integer.parseInt(JSONObject.parseObject(o.toString()).get("x").toString());
            point.y = Integer.parseInt(JSONObject.parseObject(o.toString()).get("y").toString());
            faceRectPointList.add(point);
        }
        //坐标排序，分出左上 右上 左下 右下
        boolean sorted = false;
        int n = faceRectPointList.size();
        while (!sorted) {
            for (int i = 1; i < n; i++) {
                sorted = true;
                if (faceRectPointList.get(i - 1).x > faceRectPointList.get(i).x) {
                    Point tempp1 = faceRectPointList.get(i);
                    Point tempp2 = faceRectPointList.get(i - 1);
                    faceRectPointList.set(i, tempp2);
                    faceRectPointList.set(i - 1, tempp1);
                    sorted = false;
                }
            }
            n--;
            if (n < 1) {
                break;
            }
        }

        //即先对四个点的x坐标进行冒泡排序分出左右，再根据两对坐标的y值比较分出上下
        Point[] srcPoints = new Point[4];
        if (faceRectPointList.get(0).y < faceRectPointList.get(1).y) {
            srcPoints[0] = faceRectPointList.get(0);
            srcPoints[3] = faceRectPointList.get(1);
        } else {
            srcPoints[0] = faceRectPointList.get(1);
            srcPoints[3] = faceRectPointList.get(0);
        }
        if (faceRectPointList.get(2).y < faceRectPointList.get(3).y) {
            srcPoints[1] = faceRectPointList.get(2);
            srcPoints[2] = faceRectPointList.get(3);
        } else {
            srcPoints[1] = faceRectPointList.get(3);
            srcPoints[2] = faceRectPointList.get(2);
        }
        List<Point> listSrcs = Arrays.asList(srcPoints[0], srcPoints[1], srcPoints[2], srcPoints[3]);
        return listSrcs;
    }

    /**
     * 对图片裁剪，并把裁剪完成新图片保存
     *
     * @param srcPath 图片源路径
     * @param cutPath 裁剪后存储路径
     * @param x       左上x坐标
     * @param y       左上y坐标
     * @param width   裁剪宽度
     * @param height  裁剪高度
     * @author Alan
     * @date 2021/6/23 14:28
     */
    public static BufferedImage cut(byte[] bytes, Integer x, Integer y, Integer width, Integer height) {
        new File("");
        try (InputStream is = new ByteArrayInputStream(bytes);
             ImageInputStream iis = ImageIO.createImageInputStream(is)) {
            // 读取图片文件
            /*
             * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader
             * 声称能够解码指定格式。 参数：formatName - 包含非正式格式名称 .
             *（例如 "jpeg" 或 "tiff"）等 。
             */
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(FileUtils.getRealExtension(bytes));
            ImageReader reader = it.next();
            // 获取图片流


            /*
             * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
             * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader
             * 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
             */
            reader.setInput(iis, true);
            /*
             * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O
             * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
             * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回
             * ImageReadParam 的实例。
             */
            ImageReadParam param = reader.getDefaultReadParam();
            /*
             * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象
             * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。
             */
            Rectangle rect = new Rectangle(x, y, width, height);
//            Rectangle rect = new Rectangle(x, y, 100, 10);
            // 提供一个 BufferedImage，将其用作解码像素数据的目标。
            param.setSourceRegion(rect);
            /*
             * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将
             * 它作为一个完整的 BufferedImage 返回。
             */
            return reader.read(0, param);
//             保存新图片
//            ImageIO.write(bi, Files.getFileExtension(srcPath), new File(cutPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对图片进行旋转
     *
     * @param src   旋转图片源路径
     * @param angel 旋转角度
     * @return java.awt.image.BufferedImage
     * @author Alan
     * @date 2021/6/23 14:29
     */
    public static BufferedImage Rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // 计算旋转后图片的尺寸
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);
        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = res.createGraphics();
        // 进行转换
        g2.translate((rect_des.width - src_width) / 2,
                (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

        g2.drawImage(src, null, null);
        return res;
    }

    /**
     * 计算旋转后的图片
     *
     * @param src   旋转图片源
     * @param angel 旋转角度
     * @return java.awt.Rectangle
     * @author Alan
     * @date 2021/6/23 14:30
     */
    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        // 如果旋转的角度大于90度做相应的转换
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }
}
